package com.quanyan.ic.vendingMachine.http.service.impl;

import com.alibaba.fastjson.JSON;
import com.quanyan.ic.common.paging.Limit;
import com.quanyan.ic.common.paging.PageResult;
import com.quanyan.ic.vendingMachine.constant.Constants;
import com.quanyan.ic.vendingMachine.constant.InventoryWarningLevel;
import com.quanyan.ic.vendingMachine.dao.*;
import com.quanyan.ic.common.http.exception.BizException;
import com.quanyan.ic.vendingMachine.http.request.ReqRsptRecordCondition;
import com.quanyan.ic.vendingMachine.http.request.ReqSalesRecordCondition;
import com.quanyan.ic.vendingMachine.http.service.VmAdminService;
import com.quanyan.ic.vendingMachine.model.*;
import com.quanyan.ic.vendingMachine.remoting.InventoryRemotingService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * Created by zhuo.shi on 2017/7/26.
 * 售货机管理服务
 */
@Service
public class VmAdminServiceImpl implements VmAdminService {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Autowired
    private VmCategoryDAO vmCategoryDAO;
    @Autowired
    private VmPlaceMappingDAO vmPlaceMappingDAO;
    @Autowired
    private VmGridGoodsMappingDAO vmGridGoodsMappingDAO;
    @Autowired
    private VmReplenishmentRecordDAO vmReplenishmentRecordDAO;
    @Autowired
    private VmOrderDAO vmOrderDAO;
    @Autowired
    private VmInventoryDAO vmInventoryDAO;
    @Autowired
    private InventoryRemotingService inventoryRemotingService;

    private static Logger logger = LoggerFactory.getLogger(VmAdminServiceImpl.class);

    /**
     * 售货机类型列表
     */
    @Override
    public List<VmCategory> vmCategoryList() {
        return vmCategoryDAO.listAll();
    }

    /**
     * 创建售货机，生成售货机和场馆映射，返回编号
     */
    @Override
    public String createPlaceVm(VmPlaceMapping mapping) {
        if (mapping.getPlaceId() == null
                || mapping.getCityId() == null || mapping.getCategoryId() == null) {
            return null;
        }
        if (StringUtils.isEmpty(mapping.getEquipmentId())) {
            throw new BizException("售货机序列号为空");
        }
        String vmNumber = null;
        synchronized (this) {
            //生成售货机编号
            long seqInPlace = vmPlaceMappingDAO.countPlaceVmSize(mapping.getPlaceId());             //此方法不能删除老的售货机，可禁用
            vmNumber = mapping.getCityId() + "-" + mapping.getPlaceId() + "-" + (seqInPlace + 1);
            mapping.setVmNumber(vmNumber);
            if (StringUtils.isEmpty(mapping.getName())) {        //生成备注名
                mapping.setName("售货机（" + vmNumber + "）");
            }
        }
        vmPlaceMappingDAO.insert(mapping);
        return vmNumber;
    }

    /**
     * 更新售货机海报，客服电话，补货密码
     */
    @Override
    public void updatePlaceVm(VmPlaceMappingExt ext) {
        Integer placeId = ext.getPlaceId();
        String customerTel = ext.getCustomerTel();
        if (!StringUtils.isEmpty(customerTel)) {
            redisTemplate.opsForValue().set("place:vm:customerTel:" + placeId, customerTel);
        }
        List<VmPoster> posterList = ext.getPosterList();
        List<VmUserPwd> userPwds = ext.getUserPwdList();
        vmPlaceMappingDAO.updatePlaceVmMappingExt(placeId, posterList, userPwds);
    }

    /**
     * 根据售货机编号查找售货机
     */
    @Override
    public VmPlaceMapping findPlaceVm(String vmNumber) {
        if (StringUtils.isEmpty(vmNumber)) {
            return null;
        }
        return vmPlaceMappingDAO.findByVmNumber(vmNumber);
    }

    /**
     * 验证售货机编号合法性
     */
    @Override
    public boolean validatePlaceVm(String vmNumber) {
        if (StringUtils.isEmpty(vmNumber)) {
            return false;
        }
        VmPlaceMapping mapping = vmPlaceMappingDAO.findByVmNumber(vmNumber);
        if (mapping != null
                && !StringUtils.isEmpty(mapping.getEquipmentId())) {
            return true;
        }
        return false;
    }

    /**
     * 查询售货机和场馆映射关系列表
     *
     * @param cityId   城市id
     * @param placeId  场馆id
     * @param pageNo   页码
     * @param pageSize 页显示条数
     * @return
     */
    @Override
    public PageResult<List<VmPlaceMapping>> queryPlaceVmMappingList(Integer cityId, Integer placeId, Integer pageNo, Integer pageSize) {
        if (pageNo == null || pageSize == null) {
            return null;
        }
        List<VmPlaceMapping> resultList = vmPlaceMappingDAO.queryPlaceVmMapping(
                cityId, placeId, Limit.build(pageNo, pageSize));
        long total = vmPlaceMappingDAO.countPlaceVmMapping(
                cityId, placeId);
        return PageResult.create((int) total, pageNo, pageSize, resultList);
    }

    /**
     * 禁用售货机，场馆主看不到此售货机
     *
     * @param id 售货机场馆关系映射id
     */
    @Override
    public void disablePlaceVmMapping(Integer id) {
        vmPlaceMappingDAO.disablePlaceVmMapping(id);
    }

    /**
     * 删除售货机
     *
     * @param id
     */
    @Override
    public void deletePlaceVmMapping(Integer id) {
        //
    }

    /**
     * 列出某个场馆下面所有的售货机信息，包含商品列表和库存检测
     *
     * @param placeId          场馆id
     * @param isShowInventory  是否显示库存
     * @param isCheckInventory 是否检测库存
     * @return
     */
    @Override
    public List<VendingMachine> queryPlaceVmInfoList(Integer placeId, boolean isShowInventory, boolean isCheckInventory) {
        //此场馆的所有售货机
        List<VmPlaceMapping> vmPlaceMappings =
                vmPlaceMappingDAO.queryPlaceVmMapping(null, placeId, Limit.build(1, Integer.MAX_VALUE));
        if (vmPlaceMappings == null || vmPlaceMappings.size() <= 0) {
            return null;
        }
        //显示格子货道信息
        List<VendingMachine> vendingMachines = new ArrayList<>();
        for (VmPlaceMapping vmPlaceMapping : vmPlaceMappings) {
            if (vmPlaceMapping == null) {
                continue;
            }
            VendingMachine vm = new VendingMachine();
            vm.setVmNumber(vmPlaceMapping.getVmNumber());
            vm.setName(vmPlaceMapping.getName());
            VmCategory vmCategory = vmCategoryDAO.findById(vmPlaceMapping.getCategoryId());
            if (vmCategory == null) {
                continue;
            }
            List<Integer> gridXY = vmCategory.getGridXY();
            List<Integer> gridZ = vmCategory.getGridZ();
            byte gridStartNumber = vmCategory.getGridStartNumber();
            vm.setGridXY(gridXY);
            vm.setGridInfo(generateGrindInfo(vmPlaceMapping, gridXY, gridZ, gridStartNumber, isShowInventory, isCheckInventory));

            vendingMachines.add(vm);
        }

        return vendingMachines;
    }

    /**
     * 生成某个售货机的格子货道信息
     */
    private List<GridInfo> generateGrindInfo(VmPlaceMapping vmPlaceMapping, List<Integer> gridXY, List<Integer> gridZ, Byte gridStartNumber,
                                             boolean isShowInventory, boolean isCheckInventory) {
        List<GridInfo> gridInfos = new ArrayList<>();
        byte seq = 0;
        for (int i = 0; i < gridXY.size(); i++) {    //行
            int y = gridXY.get(i);      //列
            for (int j = 0; j < y; j++) {
                GridInfo gridInfo = new GridInfo();
                String grid = (i + 1) + "-" + (j + 1);
                gridInfo.setGrid(grid);
                byte gridNumber = (byte) (gridStartNumber + seq);
                gridInfo.setGridNumber(gridNumber);
                GridGoodsMapping gridGoodsMapping = vmGridGoodsMappingDAO.find(vmPlaceMapping.getVmNumber(), grid, gridNumber);
                if (gridGoodsMapping == null) {
                    seq++;
                    gridInfos.add(gridInfo);
                    continue;
                }
                if (isShowInventory) {
                    gridInfo.setCapacity(gridZ.get(seq));
                    gridInfo.setInventory(gridGoodsMapping.getInventory());
                }
                if (isCheckInventory) {
                    byte capacity = (byte) calculateGridCapacity(grid, gridXY, gridZ);
                    byte levelWarning = (byte) calculateInventoryWarningLevel(
                            vmPlaceMapping.getPlaceId(), gridGoodsMapping.getInventory(), capacity);
                    gridInfo.setCheckLevel(levelWarning);
                }
                gridInfo.setGoodsInfo(gridGoodsMapping.getGoodsInfo());
                seq++;
                gridInfos.add(gridInfo);
            }
        }
        return gridInfos;
    }

    /**
     * 计算库存告警等级
     */
    private int calculateInventoryWarningLevel(int placeId, byte inventory, byte capacity) {
        InventoryWarningConfig config = this.getInventoryWarningConfig(placeId);
        if (config == null) {
            return InventoryWarningLevel.GREEN.getLevel();
        }
        double percent = inventory / (capacity * 1.0);
        if ((percent >= 0) && (percent <= config.getRedPercent())) {
            return InventoryWarningLevel.RED.getLevel();
        }
        if ((percent > config.getRedPercent()) && (percent <= config.getYellowPercent())) {
            return InventoryWarningLevel.YELLOW.getLevel();
        }
        return InventoryWarningLevel.GREEN.getLevel();
    }

    /**
     * 关联货道商品信息
     *
     * @param vmNumber  售货机编号
     * @param gridList  货道XY坐标
     * @param goodsInfo 要关联的商品信息
     */
    @Transactional
    @Override
    public void createGridGoodsMapping(String vmNumber, List<String> gridList, GoodsInfo goodsInfo) {
        if (StringUtils.isEmpty(vmNumber) || goodsInfo == null || goodsInfo.getId() == null || StringUtils.isEmpty(goodsInfo.getUuid())
                || gridList == null || gridList.size() <= 0) {
            throw new BizException("没有选择要关联的商品信息");
        }
        //校验商品价格
        if (goodsInfo.getPrice() == null) {  //todo去总库校验
            throw new BizException("关联的商品无价格");
        }
        //判断售货机是否存在
        VmPlaceMapping vmPlaceMapping = vmPlaceMappingDAO.findByVmNumber(vmNumber);
        if (vmPlaceMapping == null) {
            return;
        }
        VmCategory vmCategory = vmCategoryDAO.findById(vmPlaceMapping.getCategoryId());
        if (vmCategory == null) {
            return;
        }
        //关联货道商品信息
        for (String grid : gridList) {
            byte gridNumber = calculateGridNumber(grid, vmCategory.getGridXY(), vmCategory.getGridStartNumber());  //根据gridXY计算gridNumber
            if (gridNumber == -1) {          //找不到货道编号
                logger.warn("can't find gridNumber, vmNumber={}, grid={}", vmNumber, grid);
                throw new BizException("货道" + grid + "找不到编号");
            }
            GridGoodsMapping gridGoodsMapping = vmGridGoodsMappingDAO.find(vmNumber, grid, gridNumber);
            if (gridGoodsMapping != null) {  //已经存在此货道
                logger.info("already exist GridGoodsMapping {}", JSON.toJSONString(gridGoodsMapping));
                throw new BizException("货道" + grid + "已经关联商品，请先清空货道");
            }
            GridGoodsMapping mapping = new GridGoodsMapping();
            mapping.setVmNumber(vmNumber);
            mapping.setGrid(grid);
            mapping.setGridNumber(gridNumber);
            mapping.setGoodsInfo(goodsInfo);
            vmGridGoodsMappingDAO.insert(mapping);
        }
        //每次关联商品信息，都需要通知客户端去拉取新的商品列表，已在拦截器UpdateGridGoodsInterceptor里实现
    }

    /**
     * 根据货道XY坐标，计算货道的编号
     */
    private byte calculateGridNumber(String grid, List<Integer> gridXY, byte gridStartNumber) {
        byte seq = 0;
        for (int i = 0; i < gridXY.size(); i++) {
            int y = gridXY.get(i);
            for (int j = 0; j < y; j++) {
                String thisGrid = (i + 1) + "-" + (j + 1);
                if (thisGrid.equals(grid)) {
                    return (byte) (gridStartNumber + seq);
                }
                seq++;
            }
        }
        return -1;
    }

    /**
     * 清空货道
     *
     * @param vmNumber 售货机编码
     * @param gridList 货道XY坐标列表
     */
    @Transactional
    @Override
    public void clearGridGoodsMapping(String vmNumber, List<String> gridList) {
        if (StringUtils.isEmpty(vmNumber) || gridList == null || gridList.size() <= 0) {
            return;
        }
        //判断售货机是否存在
        VmPlaceMapping vmPlaceMapping = vmPlaceMappingDAO.findByVmNumber(vmNumber);
        if (vmPlaceMapping == null) {
            return;
        }
        VmCategory vmCategory = vmCategoryDAO.findById(vmPlaceMapping.getCategoryId());
        if (vmCategory == null) {
            return;
        }
        int placeId = vmPlaceMapping.getPlaceId();
        //清空货道商品信息
        for (String grid : gridList) {
            byte gridNumber = calculateGridNumber(grid, vmCategory.getGridXY(), vmCategory.getGridStartNumber());  //根据gridXY计算gridNumber
            if (gridNumber == -1) {          //找不到货道编号
                logger.warn("can't find gridNumber, vmNumber={}, grid={}", vmNumber, grid);
                throw new BizException("货道" + grid + "找不到编号");
            }
            GridGoodsMapping gridGoodsMapping = vmGridGoodsMappingDAO.find(vmNumber, grid, gridNumber);
            if (gridGoodsMapping == null) {  //此货道不存在关联的商品
                logger.info("grid not exist goods mapping, vmNumber={}, grid={}, gridNumber={}", vmNumber, grid, gridNumber);
//                throw new BizException("货道" + grid + "不存在关联的商品");
                continue;
            }
            // ** 是否需要校验此货道有未完成的订单？
            GoodsInfo goodsInfo = gridGoodsMapping.getGoodsInfo();
            int inventory = (int) gridGoodsMapping.getInventory();
            if (inventory > 0) {
                int goodsId = goodsInfo.getId();
                String goodsUuid = goodsInfo.getUuid();
                //1. 调用售货机库存服务，将此货道库存清0
                ReplenishmentInfo replenishmentInfo = new ReplenishmentInfo();
                replenishmentInfo.setGrid(grid);
                replenishmentInfo.setGridNumber(gridNumber);
                replenishmentInfo.setGoodsId(goodsId);
                replenishmentInfo.setGoodsUuid(goodsUuid);
                replenishmentInfo.setRsptCount(inventory);
                boolean updateOK = vmInventoryDAO.updateGridInventory(vmNumber, grid, gridNumber, (-1 * inventory));
                if (!updateOK) {
                    throw new BizException("清空货道" + grid + "的库存失败");
                } else {
                    //记录库存流水
                    vmInventoryDAO.insertInventoryStream(
                            populateInventoryStream(vmNumber, replenishmentInfo, goodsInfo, gridGoodsMapping.getInventory(), false));
                }
                //2. 调用总库存服务，增加此商品的库存
                List<ReplenishmentInfo> replenishmentInfoList = new ArrayList<>();
                replenishmentInfoList.add(replenishmentInfo);
                inventoryRemotingService.updateGoodsCenterInventory(placeId, vmNumber, replenishmentInfoList, true);  //入库
                //记录总库货品操作记录
                GoodsOperateRecord record = new GoodsOperateRecord();
                record.setPlaceId(vmPlaceMapping.getPlaceId());
                record.setPlaceOrderId("");
                record.setPlaceStore(vmNumber);
                record.setOperateType(11);
                record.setRemark("清空售货机货道");
                record.setGoodsId(goodsUuid);
                record.setOperateCount(inventory);
                int inventoryOfGoods = vmInventoryDAO.countVmInventoryOfGoods(vmNumber, goodsId, goodsUuid);
                record.setOpBeforeCount(inventoryOfGoods);
                record.setOpAfterCount(inventoryOfGoods - inventory);
                inventoryRemotingService.insertGoodsCenterOperateRecord(record);
            }
            //删除商品关联
            vmGridGoodsMappingDAO.delete(vmNumber, grid, gridNumber);
            logger.info("clear grid: {} {} {}, {}", vmNumber, grid, gridNumber, JSON.toJSONString(goodsInfo));
        }
        //每次清空商品关联信息，都需要通知客户端去拉取新的商品列表，已在拦截器UpdateGridGoodsInterceptor里实现
    }

    /**
     * 获取某个场馆的库存告警配置信息
     *
     * @param placeId 场馆id
     * @return
     */
    @Override
    public InventoryWarningConfig getInventoryWarningConfig(Integer placeId) {
        if (placeId == null) {
            return null;
        }
        String hashKey = Constants.REDIS_KEY_INVENTORYWARNINGCONFIG + placeId;
        InventoryWarningConfig config = new InventoryWarningConfig();
        config.setPlaceId(placeId);
        config.setRedPercent(Double.valueOf(redisTemplate.opsForHash().get(hashKey, "redPercent").toString()));
        config.setYellowPercent(Double.valueOf(redisTemplate.opsForHash().get(hashKey, "yellowPercent").toString()));
        return config;
    }

    /**
     * 设置某个场馆的库存告警配置信息
     *
     * @param config 配置信息
     */
    @Override
    public void setInventoryWarningConfig(InventoryWarningConfig config) {
        if (config == null || config.getPlaceId() == null) {
            return;
        }
        if (config.getYellowPercent() > 1 || config.getRedPercent() > 1) {
            throw new BizException("配置比例不能大于100%");
        }
        Map<String, String> map = new HashMap<>();
        map.put("redPercent", String.valueOf(config.getRedPercent()));
        map.put("yellowPercent", String.valueOf(config.getYellowPercent()));
        redisTemplate.opsForHash().putAll(Constants.REDIS_KEY_INVENTORYWARNINGCONFIG + config.getPlaceId(), map);
    }

    /**
     * 查询补货记录列表
     *
     * @param condition 查询条件
     * @return
     */
    @Override
    public PageResult<List<ReplenishmentRecord>> queryRsptRecordList(ReqRsptRecordCondition condition) {
        Integer pageNo = condition.getPageNum();
        Integer pageSize = condition.getPageSize();
        if (pageNo == null || pageSize == null) {
            return null;
        }
        List<ReplenishmentRecord> replenishmentRecords = vmReplenishmentRecordDAO.queryRsptRecordList(
                condition, Limit.build(condition.getPageNum(), condition.getPageSize()));
        if (!CollectionUtils.isEmpty(replenishmentRecords)) {
            for (ReplenishmentRecord record : replenishmentRecords) {
                String vmNumber = record.getVmNumber();
                VmPlaceMapping vmPlaceMapping = vmPlaceMappingDAO.findByVmNumber(vmNumber);
                if (vmPlaceMapping == null) {
                    continue;
                }
                VmCategory vmCategory = vmCategoryDAO.findById(vmPlaceMapping.getCategoryId());
                if (vmCategory == null) {
                    continue;
                }
                record.setGridXY(vmCategory.getGridXY());
            }
        }
        long total = vmReplenishmentRecordDAO.countRsptRecordList(condition);
        return PageResult.create((int) total, condition.getPageNum(), condition.getPageSize(), replenishmentRecords);
    }

    /**
     * 查询销售记录列表
     *
     * @param condition 查询条件
     * @return
     */
    @Override
    public PageResult<List<SalesRecord>> querySalesRecordList(ReqSalesRecordCondition condition) {
        Integer pageNo = condition.getPageNum();
        Integer pageSize = condition.getPageSize();
        if (pageNo == null || pageSize == null) {
            return null;
        }
        List<SalesRecord> salesRecords = vmOrderDAO.querySalesRecordList(condition);
        int total = vmOrderDAO.countSalesRecordList(condition);
        return PageResult.create(total, pageNo, pageSize, salesRecords);
    }

    /**
     * 补货操作
     *
     * @param vmNumber     售货机编号
     * @param rsptInfoList 补货信息列表
     */
    @Transactional
    @Override
    public synchronized void goodsReplenishment(String vmNumber, List<ReplenishmentInfo> rsptInfoList, VmUserPwd userPwd) {
        VmPlaceMapping mapping = vmPlaceMappingDAO.findByVmNumber(vmNumber);
        if (mapping == null) {
            throw new BizException("没有找到售货机" + vmNumber);
        }
        VmCategory vmCategory = vmCategoryDAO.findById(mapping.getCategoryId());
        List<Integer> gridXY = vmCategory.getGridXY();
        Byte gridStartNumber = vmCategory.getGridStartNumber();

        //获取补货前货道快照
        List<GridInfo> gridInfosBefore = null;
        List<VendingMachine> vmList = this.queryPlaceVmInfoList(mapping.getPlaceId(), true, false);
        for (VendingMachine vm : vmList) {
            if (vmNumber.equals(vm.getVmNumber())) {
                gridInfosBefore = vm.getGridInfo();
                break;
            }
        }

        //给每个货道补货
        for (ReplenishmentInfo rsptInfo : rsptInfoList) {
            String grid = rsptInfo.getGrid();
            Byte gridNumber = rsptInfo.getGridNumber();
            //校验此货道的编号
            Byte gridNumber_cal = calculateGridNumber(grid, gridXY, gridStartNumber);
            if (gridNumber.byteValue() != gridNumber_cal.byteValue()) {
                throw new BizException("货道[" + grid + "]的编号（" + gridNumber + "）校验不通过，编号应为: " + gridNumber_cal);
            }
            //查找此货道信息，是否已经被后台清空货道
            GridGoodsMapping gridGoodsMapping = vmGridGoodsMappingDAO.find(vmNumber, grid, gridNumber);
            if (gridGoodsMapping == null) {
                throw new BizException("货道[" + grid + "]还未关联任何商品");
            }
            //检查此货道商品库存，最大可容商品数
            Integer rsptCount = rsptInfo.getRsptCount();
            Byte inventory = gridGoodsMapping.getInventory();
            int gridCapacity = calculateGridCapacity(grid, gridXY, vmCategory.getGridZ());
            if (rsptCount > 0 && ((rsptCount + inventory) > gridCapacity)) {  //方法的synchronized保证此方法事务执行完后面请求才可以继续进入方法重新获取库存
                throw new BizException("货道[" + grid + "]已有库存[" + inventory + "]，补货[" + rsptCount + "]，超过此货道最大容量[" + gridCapacity + "]");
            }
            //中央仓库库存出库
            List<ReplenishmentInfo> rsptList = new ArrayList<>();
            rsptList.add(rsptInfo);
            inventoryRemotingService.updateGoodsCenterInventory(mapping.getPlaceId(), vmNumber, rsptList, false);
            //记录总库货品操作记录
            GoodsOperateRecord record = new GoodsOperateRecord();
            record.setPlaceId(mapping.getPlaceId());
            record.setPlaceOrderId("");
            record.setPlaceStore(vmNumber);
            record.setOperateType(10);
            record.setRemark("售货机补货");
            record.setGoodsId(gridGoodsMapping.getGoodsInfo().getUuid());
            record.setOperateCount(rsptCount);
            int inventoryOfGoods = vmInventoryDAO.countVmInventoryOfGoods(vmNumber, gridGoodsMapping.getGoodsInfo().getId(), gridGoodsMapping.getGoodsInfo().getUuid());
            record.setOpBeforeCount(inventoryOfGoods);
            record.setOpAfterCount(inventoryOfGoods - inventory);
            inventoryRemotingService.insertGoodsCenterOperateRecord(record);
            //本地售货机货道库存，入库
            boolean ret = vmInventoryDAO.updateGridInventory(vmNumber, grid, gridNumber, rsptCount);
            if (!ret) {
                throw new BizException("货道[" + grid + "]更新库存失败！");
            }
            logger.info("call local vm inventory service, update inventory ok");
            //生成此货道库存变更流水
            vmInventoryDAO.insertInventoryStream(
                    populateInventoryStream(vmNumber, rsptInfo, gridGoodsMapping.getGoodsInfo(), inventory, true));
            logger.info("grid goods replenishment OK，vmNumber=[{}], grid=[{}], inventory=[{}]，rsptCount=[{}]，capacity[{}]", vmNumber, grid, inventory, rsptCount, gridCapacity);
        }
        //生成补货记录
        vmInventoryDAO.insertReplenishmentRecord(
                populateReplenishmentRecord(vmNumber, mapping, userPwd, rsptInfoList, gridInfosBefore));
    }

    /**
     * 生成补货记录信息
     */
    private ReplenishmentRecord populateReplenishmentRecord(
            String vmNumber, VmPlaceMapping mapping, VmUserPwd userPwd, List<ReplenishmentInfo> rsptInfoList, List<GridInfo> gridInfoList) {
        ReplenishmentRecord record = new ReplenishmentRecord();
        record.setVmNumber(vmNumber);
        record.setVmName(mapping.getName());
        record.setPlaceId(mapping.getPlaceId());
        record.setPlaceName(mapping.getPlaceName());
        record.setOpUser(userPwd.getUserName());
        record.setOpPwd(userPwd.getPassword());
        record.setOpTime(new Date());
        List<GridInfo> gridInfoList1 = JSON.parseArray(JSON.toJSONString(gridInfoList), GridInfo.class);
        if (gridInfoList1 != null) {
            record.setSnapshoot_1(gridInfoList1);
        }
        Map<String, RsptGoodsSummary> tempMap = new HashMap<>();  //计算summary临时变量
        for (ReplenishmentInfo rsptInfo : rsptInfoList) {
            String key = rsptInfo.getGoodsUuid() + rsptInfo.getGoodsId();
            RsptGoodsSummary summary = new RsptGoodsSummary();
            summary.setGoodsId(rsptInfo.getGoodsId());
            summary.setGoodsName(rsptInfo.getGoodsName());
//            summary.setGoodsPrice(gridGoodsMapping.get);
            summary.setRsptCount(rsptInfo.getRsptCount());
            if (!tempMap.containsKey(key)) {
                tempMap.put(key, summary);
            } else {
                summary.setRsptCount(tempMap.get(key).getRsptCount() + rsptInfo.getRsptCount());
                tempMap.put(key, summary);
            }
            if (gridInfoList != null) {
                for (GridInfo gridInfo : gridInfoList) {
                    if (gridInfo.getGrid().equals(rsptInfo.getGrid())) {
                        gridInfo.setInventory((byte) (gridInfo.getInventory() + rsptInfo.getRsptCount()));  //增加后的库存
                    }
                }
            }
        }
        List<RsptGoodsSummary> summaries = new ArrayList<>();
        Set<String> uuidids = tempMap.keySet();
        for (String uuidid : uuidids) {
            summaries.add(tempMap.get(uuidid));
        }

        record.setSnapshoot_2(gridInfoList);
        record.setSummaryList(summaries);
        return record;
    }

    /**
     * 生成库存变更流水
     */
    private InventoryStream populateInventoryStream(
            String vmNumber, ReplenishmentInfo rsptInfo, GoodsInfo goodsInfo, Byte orginalInventory, boolean input) {
        InventoryStream stream = new InventoryStream();
        stream.setVmNumber(vmNumber);
        stream.setOriginalInventory(orginalInventory);
        rsptInfo.setGoodsId(goodsInfo.getId());
        rsptInfo.setGoodsUuid(goodsInfo.getUuid());
        rsptInfo.setGoodsName(goodsInfo.getName());
        if (input) {
            stream.setOpCount(rsptInfo.getRsptCount());
        } else {
            int count = -1 * rsptInfo.getRsptCount();
            stream.setOpCount(count);
        }
        stream.setReplenishmentInfo(rsptInfo);
        return stream;
    }

    /**
     * 根据货道XY坐标，计算货道的最大容量
     */
    private int calculateGridCapacity(String grid, List<Integer> gridXY, List<Integer> gridZ) {
        byte seq = 0;
        for (int i = 0; i < gridXY.size(); i++) {
            int y = gridXY.get(i);
            for (int j = 0; j < y; j++) {
                String thisGrid = (i + 1) + "-" + (j + 1);
                if (thisGrid.equals(grid)) {
                    return gridZ.get(seq);
                }
                seq++;
            }
        }
        return -1;
    }

    /**
     * 查找售货机
     *
     * @param vmNumber       售货机编号
     * @param showInventory  是否显示库存
     * @param checkInventory 是否检测库存
     * @return
     */
    @Override
    public VendingMachine findVendingMachine(String vmNumber, boolean showInventory, boolean checkInventory) {
        VmPlaceMapping mapping = findPlaceVm(vmNumber);
        if (mapping == null) {
            throw new BizException("没有找到售货机" + vmNumber);
        }
        List<VendingMachine> vmList = this.queryPlaceVmInfoList(mapping.getPlaceId(), showInventory, checkInventory);
        for (VendingMachine vm : vmList) {
            if (vmNumber.equals(vm.getVmNumber())) {
                return vm;
            }
        }
        return null;
    }

    /**
     * 获取售货机售后电话
     *
     * @param placeId 场馆id
     * @return
     */
    @Override
    public String findVmCustomerTel(Integer placeId) {
        return redisTemplate.opsForValue().get("place:vm:customerTel:" + placeId);
    }

    /**
     * 获取售货机售后电话
     *
     * @param vmNumber 售货机编号
     * @return
     */
    @Override
    public String findVmCustomerTel(String vmNumber) {
        if (StringUtils.isEmpty(vmNumber)) {
            return null;
        }
        VmPlaceMapping vmPlaceMapping = vmPlaceMappingDAO.findByVmNumber(vmNumber);
        if (vmPlaceMapping != null) {
            return redisTemplate.opsForValue().get("place:vm:customerTel:" + vmPlaceMapping.getPlaceId());
        }
        return null;
    }

    /**
     * 获取售货机海报
     *
     * @param placeId 场馆id
     * @return
     */
    @Override
    public List<VmPoster> findVmPoster(Integer placeId) {
        return vmPlaceMappingDAO.findVmPoster(placeId);
    }

    /**
     * 删除海报
     */
    @Override
    public void deleteVmPoster(Integer id) {
        vmPlaceMappingDAO.deleteVmPoster(id);
    }

    @Override
    public void deleteUserPwd(Integer id) {
        vmPlaceMappingDAO.deleteVmUserPwd(id);
    }

    /**
     * 获取售货机用户名密码
     *
     * @param placeId 场馆id
     * @return
     */
    @Override
    public List<VmUserPwd> findVmUserPwd(Integer placeId) {
        return vmPlaceMappingDAO.findVmUserPwd(placeId);
    }
}
